#pragma once

#include <tuple>

template<class F, class T, bool Stop, int N>
struct call_impl {
    static void call(F f, T t){
        if constexpr( std::is_arithmetic_v< std::tuple_element_t<N, T>> ){
            f(std::get<N>(t));
        }
        call_impl<F, T, N + 1 == std::tuple_size_v<T>, N + 1>::call(f, t);
    }
};

template<class F, class T, int N>
struct call_impl<F, T, true, N>
{
    static void call(F f, T t){}
};

template<class F, class T, int N = 0>
void caller(F f, T t){
    if constexpr (
        std::is_arithmetic_v<std::tuple_element_t<N, T>>
            && ! std::is_same_v<char, std::tuple_element_t<N, T>>
    ){
        f(std::get<N>(t));
    }
    if constexpr ( N + 1 != std::tuple_size_v<T> )
        caller<F, T, N + 1>(f, t);
}

template <typename... Ts>
double tuple_sum(const std::tuple<Ts...>& tpl){
    double sum = 0;
    auto f = [&sum](auto n){ sum += n; };
    caller(f, tpl);
//     call_impl::call(f, tpl);
    return sum;
}
